home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
nethack.lha
/
nethack-3.1
/
src
/
quest.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-24
|
8KB
|
331 lines
/* SCCS Id: @(#)quest.c 3.1 92/11/13 */
/* Copyright 1991, M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#ifdef MULDGN
/* quest dungeon branch routines. */
#include "quest.h"
#include "qtext.h"
#define Not_firsttime (on_level(&u.uz0, &u.uz))
#define Qstat(x) (quest_status.x)
static void NDECL(on_start);
static void NDECL(on_locate);
static void NDECL(on_goal);
static boolean NDECL(not_capable);
static boolean NDECL(not_pure);
static void FDECL(expulsion, (BOOLEAN_P));
static void NDECL(chat_with_leader);
static void NDECL(chat_with_nemesis);
static void NDECL(chat_with_guardian);
static void
on_start() {
if(!Qstat(first_start)) {
qt_pager(QT_FIRSTTIME);
Qstat(first_start) = TRUE;
} else if((u.uz0.dnum != u.uz.dnum) || (u.uz0.dlevel < u.uz.dlevel)) {
if(Qstat(not_ready) <= 2) qt_pager(QT_NEXTTIME);
else qt_pager(QT_OTHERTIME);
}
}
static void
on_locate() {
if(!Qstat(first_locate)) {
qt_pager(QT_FIRSTLOCATE);
Qstat(first_locate) = TRUE;
} else if(u.uz0.dlevel < u.uz.dlevel)
qt_pager(QT_NEXTLOCATE);
}
static void
on_goal() {
if(!Qstat(made_goal)) {
qt_pager(QT_FIRSTGOAL);
Qstat(made_goal) = 1;
} else {
qt_pager(QT_NEXTGOAL);
if(Qstat(made_goal) < 7) Qstat(made_goal)++;
}
}
void
quest_init() {
/*
* Special setup modifications here:
*
* Unfortunately, this is going to have to be done on each level,
* on start-up, and on entry, since you lose the permonst mods
* across a save/restore :-)
*
* 1 - The Rogue Leader is the Tourist Nemesis.
* 1 - Elves can have one of two different leaders, work it out here.
* 2 - Priests start with a random alignment - convert the leader and
* guardians here.
*/
#ifdef TOURIST
if(pl_character[0] == 'T' && Is_nemesis(&u.uz)) {
register struct monst *mtmp;
mons[PM_MASTER_OF_THIEVES].msound = MS_NEMESIS;
mons[PM_MASTER_OF_THIEVES].mflags2 &= ~(M2_PEACEFUL);
mons[PM_MASTER_OF_THIEVES].mflags2 |= (M2_NASTY|M2_STALK|M2_HOSTILE);
mons[PM_MASTER_OF_THIEVES].mflags3 = M3_WANTSARTI | M3_WAITFORU;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) /* find the leader... */
if(mtmp->data->msound == MS_NEMESIS) {
set_malign(mtmp); /* changed M2_PEACEFUL */
break;
}
} else
#endif
if(pl_character[0] == 'E' && flags.female && Is_qstart(&u.uz)) {
register struct monst *mtmp;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) /* find the leader... */
if(mtmp->data->msound == MS_LEADER) {
mtmp->data = &mons[PM_ELWING]; /* sex-change */
break;
}
} else if(pl_character[0] == 'P' && Is_qstart(&u.uz)) {
register struct monst *mtmp;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) /* find leader & guards */
if(mtmp->data->msound == MS_LEADER ||
mtmp->data->msound == MS_GUARDIAN) {
/* use game-start alignment for reference */
mtmp->data->maligntyp = u.ualignbase[1]*3;
mtmp->mpeaceful = TRUE;
set_malign(mtmp); /* mpeaceful may have changed */
}
}
}
void
onquest() {
if(Not_firsttime) return;
if(!Is_special(&u.uz)) return;
if(Is_qstart(&u.uz)) on_start();
else if(Is_qlocate(&u.uz) && u.uz.dlevel > u.uz0.dlevel) on_locate();
else if(Is_nemesis(&u.uz)) on_goal();
return;
}
void
nemdead() {
if(!Qstat(killed_nemesis)) {
Qstat(killed_nemesis) = TRUE;
qt_pager(QT_KILLEDNEM);
}
}
void
artitouch() {
if(!Qstat(touched_artifact)) {
Qstat(touched_artifact) = TRUE;
qt_pager(QT_GOTIT);
exercise(A_WIS, TRUE);
}
}
/* external hook for do.c (level change check) */
boolean
ok_to_quest() {
return(Qstat(got_quest));
}
static boolean
not_capable() {
return(u.ulevel < MIN_QUEST_LEVEL);
}
/* TODO: This one needs tuning. */
static boolean
not_pure() {
#ifdef WIZARD
if(wizard && (u.ualign.record < MIN_QUEST_ALIGN)) {
You("are currently %d and require %d.",
u.ualign.record, MIN_QUEST_ALIGN);
if(yn_function("adjust?", NULL, 'y') == 'y')
u.ualign.record = MIN_QUEST_ALIGN;
}
#endif
return(u.ualign.record < MIN_QUEST_ALIGN);
}
/*
* Expell the player to the stairs on the parent of the quest dungeon.
*
* This assumes that the hero is currently _in_ the quest dungeon and that
* there is a single branch to and from it.
*/
static void
expulsion(seal)
boolean seal;
{
branch *br;
d_level *dest;
br = dungeon_branch("The Quest");
dest = (br->end1.dnum == u.uz.dnum) ? &br->end2 : &br->end1;
assign_level(&u.utolev, dest);
u.utotype = 1; /* portal */
if (seal) { /* remove the portal to the quest - sealing it off */
u.utotype |= 0200;
u.uevent.qexpelled = 1;
}
}
static void
chat_with_leader()
{
/* Rule 0: Cheater checks. */
if(u.uhave.questart && !Qstat(met_nemesis))
Qstat(cheater) = TRUE;
/* It is possible for you to get the amulet without completing
* the quest. If so, try to induce the player to quest.
*/
if(Qstat(got_thanks)) {
/* Rule 1: You've gone back with/whithout the amulet. */
if(u.uhave.amulet) qt_pager(QT_HASAMULET);
/* Rule 2: You've gone back before going for the amulet. */
else qt_pager(QT_POSTHANKS);
}
/* Rule 3: You've got the artifact and are back to return it. */
else if(u.uhave.questart) {
if(u.uhave.amulet) qt_pager(QT_HASAMULET);
else qt_pager(QT_OFFEREDIT);
Qstat(got_thanks) = TRUE;
u.uevent.qcompleted = 1; /* you did it! */
/* Rule 4: You haven't got the artifact yet. */
} else if(Qstat(got_quest)) qt_pager(rn1(10, QT_ENCOURAGE));
/* Rule 5: You aren't yet acceptable - or are you? */
else {
if(!Qstat(met_leader)) {
qt_pager(QT_FIRSTLEADER);
Qstat(met_leader) = TRUE;
Qstat(not_ready) = 0;
} else qt_pager(QT_NEXTLEADER);
if(not_capable()) {
qt_pager(QT_BADLEVEL);
exercise(A_WIS, TRUE);
expulsion(FALSE);
} else if(not_pure()) {
qt_pager(QT_BADALIGN);
if(Qstat(not_ready) == MAX_QUEST_TRIES) {
qt_pager(QT_LASTLEADER);
expulsion(TRUE);
} else {
Qstat(not_ready)++;
exercise(A_WIS, TRUE);
expulsion(FALSE);
}
} else { /* You are worthy! */
qt_pager(QT_ASSIGNQUEST);
exercise(A_WIS, TRUE);
Qstat(got_quest) = TRUE;
}
}
}
void
leader_speaks(mtmp)
register struct monst *mtmp;
{
/* maybe you attacked leader? */
if(!mtmp->mpeaceful) {
Qstat(pissed_off) = TRUE;
mtmp->data->mflags3 = 0; /* end the inaction */
}
if(Qstat(pissed_off)) {
qt_pager(QT_LASTLEADER);
expulsion(TRUE);
} else chat_with_leader();
}
static void
chat_with_nemesis()
{
/* The nemesis will do most of the talking, but... */
qt_pager(rn1(10, QT_DISCOURAGE));
if(!Qstat(met_nemesis)) Qstat(met_nemesis++);
}
void
nemesis_speaks()
{
if(!Qstat(in_battle)) {
if(u.uhave.questart) qt_pager(QT_NEMWANTSIT);
else if(!Qstat(made_goal)) qt_pager(QT_FIRSTNEMESIS);
else if(Qstat(made_goal) < 3) qt_pager(QT_NEXTNEMESIS);
else if(Qstat(made_goal) < 7) qt_pager(QT_OTHERNEMESIS);
else if(!rn2(5)) qt_pager(rn1(10, QT_DISCOURAGE));
if(Qstat(made_goal) < 7) Qstat(made_goal)++;
Qstat(met_nemesis) = TRUE;
} else /* he will spit out random maledictions */
if(!rn2(5)) qt_pager(rn1(10, QT_DISCOURAGE));
}
static void
chat_with_guardian()
{
/* These guys/gals really don't have much to say... */
qt_pager(rn1(5, QT_GUARDTALK));
}
void
quest_chat(mtmp)
register struct monst *mtmp;
{
switch(mtmp->data->msound) {
case MS_LEADER: chat_with_leader(); break;
case MS_NEMESIS: chat_with_nemesis(); break;
case MS_GUARDIAN: chat_with_guardian(); break;
default: impossible("quest_chat: Unknown quest character %s.",
mon_nam(mtmp));
}
}
void
quest_talk(mtmp)
register struct monst *mtmp;
{
switch(mtmp->data->msound) {
case MS_LEADER: leader_speaks(mtmp); break;
case MS_NEMESIS: nemesis_speaks(); break;
default: break;
}
}
void
quest_stat_check(mtmp)
struct monst *mtmp;
{
if(mtmp->data->msound == MS_NEMESIS)
Qstat(in_battle) =
(mtmp->mcanmove && !mtmp->msleep && monnear(mtmp, u.ux, u.uy));
}
#endif /* MULDGN */
/*quest.c*/